package com.moli.iov.down.remote.impl;

import com.moli.iov.base.model.dto.res.VehicleBaseResDto;
import com.moli.iov.base.remote.IVehicleBaseRemoteService;
import com.moli.iov.down.command.SendCommandService;
import com.moli.iov.down.command.design.factory.CommandReqDtoFactory;
import com.moli.iov.down.command.mq.SendCache;
import com.moli.iov.down.enums.FailMsgEnum;
import com.moli.iov.down.enums.OperateStatusEnum;
import com.moli.iov.down.enums.OperateTypeEnum;
import com.moli.iov.down.enums.OperatorResultEnum;
import com.moli.iov.down.enums.SourceEnum;
import com.moli.iov.down.model.dto.remoting.CommandDto;
import com.moli.iov.down.model.dto.remoting.CommandReqDto;
import com.moli.iov.down.model.dto.req.VehicleCommandDto;
import com.moli.iov.down.model.dto.req.VehicleCommandThirdDto;
import com.moli.iov.down.model.po.VehicleCommand;
import com.moli.iov.down.model.po.VehicleParam;
import com.moli.iov.down.remote.IVehicleCommandThirdRemoteService;
import com.moli.iov.down.remote.IVehicleParamRemoteService;
import com.moli.iov.down.service.IVehicleCommandService;
import com.moli.iov.down.service.IVehicleParamService;
import com.moli.iov.exception.BusinessException;
import com.moli.iov.rest.RestResponse;
import com.moli.iov.util.CommonUtils;
import com.moli.iov.util.SnowflakeUtils;
import com.moli.iov.util.ValidationUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 控车业务  第三方
 * </p>
 *
 * @author zql
 * @since 2020/4/2 13:46
 */
@Slf4j
@Service(group = "${service.group}")
public class VehicleCommandThirdRemoteServiceImpl implements IVehicleCommandThirdRemoteService {

    @Autowired
    private IVehicleParamRemoteService vehicleParamRemoteService;

    @Reference(group = "${service.group}", check = false)
    private IVehicleBaseRemoteService vehicleBaseRemoteService;

    @Autowired
    private IVehicleParamService vehicleParamService;

    @Autowired
    private SendCache sendCache;

    @Autowired
    private IVehicleCommandService vehicleCommandService;

    @Autowired
    private SendCommandService sendCommandService;

    /**
     * 控车
     */
    @Override
    public RestResponse sendCommand(VehicleCommandThirdDto vehicleCommandThirdDto) {

        String message = null;
        // 参数校验， 返回车辆信息
        try {
            sendControlValid(vehicleCommandThirdDto);
        } catch (BusinessException e) {
            message = e.getMessage();
        }
        // 组装数据
        VehicleCommand vehicleCommand = assemblyVehicleCommand(vehicleCommandThirdDto);

        // 保存数据
        if (!StringUtils.isEmpty(message)) {
            vehicleCommand.setStatus(3);
            vehicleCommand.setResult(2);
            vehicleCommand.setResultMemo(message);
        }
        vehicleCommandService.saveCommand(vehicleCommand);

        if (vehicleCommand != null && vehicleCommand.getResult() != null && vehicleCommand.getResult() == 2) {
            return RestResponse.failure(vehicleCommand.getResultMemo());
        }

        //组装命令请求DTO
        List<CommandDto> commandDtos = assemblyCommandReqDto(vehicleCommand);

        if (commandDtos.isEmpty()) {
            return RestResponse.failure("车辆离线");
        }


        // 发送命令
        sendCommandService.sendCommand(commandDtos);
        return RestResponse.success(vehicleCommand.getId());
    }

    /**
     * 参数校验
     */
    private VehicleCommandThirdDto sendControlValid(VehicleCommandThirdDto vehicleCommandThirdDto) {

        ValidationUtils
                .restResponseValidate(vehicleCommandThirdDto, VehicleCommandDto.Control.class);

        //查询车辆信息
        RestResponse<VehicleBaseResDto> vehicleCompanyIdByVin = vehicleBaseRemoteService
                .getVehicleCompanyIdByVin(vehicleCommandThirdDto.getVin());
        if (!vehicleCompanyIdByVin.flag) {
            throw new BusinessException(vehicleCompanyIdByVin.getMessage());
        }
        if (vehicleCompanyIdByVin == null
                || (vehicleCompanyIdByVin.getData() != null && StringUtils.isEmpty(vehicleCompanyIdByVin.getData().getVin()))) {
            throw new BusinessException("车辆不存在");
        }

        VehicleBaseResDto vehicleBaseResDto = vehicleCompanyIdByVin.getData();

        boolean isAuth = !vehicleCommandThirdDto.getSysCompanyId()
                .equals(vehicleBaseResDto.getCompanyId());
        if (isAuth) {
            throw new BusinessException("无当前车辆权限");
        }

        List<String> onlineVins =
                vehicleParamRemoteService.getOnlineVins(Arrays.asList(vehicleCommandThirdDto.getVin()));
        if (!onlineVins.contains(vehicleCommandThirdDto.getVin())) {
            throw new BusinessException(FailMsgEnum.OFFLINE.getMsg());
        }


        vehicleCommandThirdDto.setCompanyId(vehicleBaseResDto.getCompanyId());
        vehicleCommandThirdDto.setCompanyName(vehicleBaseResDto.getCompanyName());
        vehicleCommandThirdDto.setLicense(vehicleBaseResDto.getLicense());
        return vehicleCommandThirdDto;
    }

    /**
     * 组装 VehicleCommand
     */
    private VehicleCommand assemblyVehicleCommand(VehicleCommandThirdDto vehicleCommandThirdDto) {
        VehicleParam vehicleParamByVin =
                vehicleParamService.getVehicleParamByVin(vehicleCommandThirdDto.getVin());

        VehicleCommand vehicleCommand = new VehicleCommand();
        CommonUtils.copyProperties(vehicleCommandThirdDto, vehicleCommand);

        vehicleCommand.setId(SnowflakeUtils.getId());

        vehicleCommand.setOperateType(vehicleCommandThirdDto.getOperateType());
        vehicleCommand
                .setOperateTypeName(OperateTypeEnum.getMsg(vehicleCommandThirdDto.getOperateType()));
        vehicleCommand.setCommandNo(sendCache.getSerialNumber(vehicleCommandThirdDto.getVin()));
        vehicleCommand.setStatus(OperateStatusEnum.STAY_SEND.getFlag());
        vehicleCommand.setResult(OperatorResultEnum.INIT.getFlag());
        vehicleCommand.setCreateTime(new Date());
        if (vehicleParamByVin != null) {
            vehicleCommand.setIccid(vehicleParamByVin.getIccid());
        }

        vehicleCommand.setSource(SourceEnum.THIRD.getFlag());

        RestResponse<String> licenseRes = vehicleBaseRemoteService.queryLicenseByVin(vehicleCommand.getVin());
        if (licenseRes != null && licenseRes.flag && !StringUtils.isEmpty(licenseRes.getData())) {
            vehicleCommand.setLicense(licenseRes.getData());
        }
        return vehicleCommand;
    }

    /**
     * 组装命令DTO
     */
    private List<CommandDto> assemblyCommandReqDto(VehicleCommand vehicleCommand) {

        Integer frequency =
                vehicleCommand.getFrequencyExtend() != null ? vehicleCommand.getFrequencyExtend()
                        .getFrequency() : null;
        String ip =
                vehicleCommand.getIpAndPortExtend() != null ? vehicleCommand.getIpAndPortExtend().getIp()
                        : null;
        Integer port =
                vehicleCommand.getIpAndPortExtend() != null ? vehicleCommand.getIpAndPortExtend().getPort()
                        : null;

        CommandReqDto commandReqDto = new CommandReqDto();
        CommonUtils.copyProperties(vehicleCommand, commandReqDto);
        commandReqDto.setIsRetry(OperateTypeEnum.isRetry(vehicleCommand.getOperateType()));
        commandReqDto.setFrequency(frequency);
        commandReqDto.setIp(ip);
        commandReqDto.setPort(port);

        CommandDto commandDto = CommandReqDtoFactory.getCommandReqDto(commandReqDto);
        commandDto.setCommandNo(vehicleCommand.getCommandNo());
        commandDto.setUrl(vehicleCommand.getUpgradeUrl());

        List<CommandDto> commandDtos = new ArrayList<>();
        commandDtos.add(commandDto);

        return commandDtos;
    }
}
